package com.econvent.common.conn;

import com.alibaba.druid.pool.DruidDataSource;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.dbcp2.BasicDataSource;
import com.mchange.v2.c3p0.*;

import javax.sql.DataSource;

/**
 * 实现多数据源的管理-根据配置文件或者数据库配置构建数据库连接池对象
 *
 * @author xiekun
 * @since 1.0
 */

@Slf4j
public class DynamicDataSourceBuilder {
    private DataSource tarDataSource ;

    /**
     * 构建数据库连接池
     * @param driverClassName 数据库驱动名称
     * @param dbConnUrl 数据库连接Url
     * @param userName 用户名
     * @param password 数据库密码
     * @param minPoolNum 最小连接数
     * @param maxPoolNum 最大连接数
     * @param minEvictableIdleTimeMillis 连接保持空闲而不被驱逐的最长时间
     * @param connPoolType 数据库连接池类型
     *
     * @return DataSource 连接池对象
     * **/
    public DynamicDataSourceBuilder(String driverClassName,String dbConnUrl, String userName,String password, int minPoolNum, int maxPoolNum,
                                      long minEvictableIdleTimeMillis , String connPoolType) {
        try {
            if (connPoolType.equalsIgnoreCase("dbcp")) { //如果使用C3P0连接池
                BasicDataSource dbcpDataSource = new BasicDataSource();
                dbcpDataSource.setUrl(dbConnUrl);
                dbcpDataSource.setUsername(userName);
                dbcpDataSource.setPassword(password);
                dbcpDataSource.setInitialSize(minPoolNum);
                dbcpDataSource.setMaxTotal(maxPoolNum);
                dbcpDataSource.setMaxOpenPreparedStatements(50);
                dbcpDataSource.setMinIdle(3); //连接池最小空闲数
                dbcpDataSource.setMaxIdle(5); //连接池最大空闲数

                if (minEvictableIdleTimeMillis > 0) {
                    dbcpDataSource.setMinEvictableIdleTimeMillis(1000 * minEvictableIdleTimeMillis); //最小空闲数，如果连接数量大于MinIdle,如果空闲市场 > MinEvictableIdleTimeMillis 则会关闭
                }

                this.setTarDataSource(dbcpDataSource);
            }  else if (connPoolType.equalsIgnoreCase("druid")) {
                DruidDataSource druidDataSource = new DruidDataSource();
                druidDataSource.setUrl(dbConnUrl);
                druidDataSource.setUsername(userName);
                druidDataSource.setPassword(password);
                druidDataSource.setDriverClassName(driverClassName);
                druidDataSource.setInitialSize(minPoolNum);
                druidDataSource.setMinIdle(3);
                druidDataSource.setMaxActive(maxPoolNum);
                druidDataSource.setMaxWait(60000L);
                druidDataSource.setTimeBetweenEvictionRunsMillis(60000L);
                druidDataSource.setMinEvictableIdleTimeMillis(300000L);
                druidDataSource.setMaxOpenPreparedStatements(50);

                druidDataSource.setPoolPreparedStatements(false);
                druidDataSource.setFilters("stat");
                druidDataSource.init();

                this.setTarDataSource(druidDataSource);
            } else if(connPoolType.equalsIgnoreCase("c3p0")){
                ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
                comboPooledDataSource.setJdbcUrl(dbConnUrl);
                comboPooledDataSource.setUser(userName);
                comboPooledDataSource.setPassword(password);
                comboPooledDataSource.setMaxPoolSize(maxPoolNum);
                comboPooledDataSource.setMinPoolSize(minPoolNum);
                comboPooledDataSource.setMaxIdleTime(60000);
                comboPooledDataSource.setInitialPoolSize(minPoolNum);

                this.setTarDataSource(comboPooledDataSource);
            } else { //如果使用hikari连接池,便于以后Spring boot扩展
                HikariDataSource hikariDataSource = new HikariDataSource();
                hikariDataSource.setJdbcUrl(dbConnUrl);
                hikariDataSource.setUsername(userName);
                hikariDataSource.setPassword(password);
                hikariDataSource.setMaximumPoolSize(maxPoolNum);
                hikariDataSource.setMinimumIdle(3);
                //hikariDataSource.setT

                this.setTarDataSource(hikariDataSource);
            }
        } catch (  Exception e) {
            log.error("DynamicDataSourceBuilder build dataSource error , the eror is {} " , e);
        }
    }

    public DataSource getTarDataSource() {
        return tarDataSource;
    }

    public void setTarDataSource(DataSource tarDataSource) {
        this.tarDataSource = tarDataSource;
    }

    /**
     * 关闭对应的数据库连接池
     *
     * @return
     * **/
    public void destroy() {
        if(this.tarDataSource == null) {
            return ;
        }

        try {
            if (tarDataSource instanceof BasicDataSource) {
                ((BasicDataSource)tarDataSource).close();
            } else if (tarDataSource instanceof ComboPooledDataSource) {
                ((BasicDataSource)tarDataSource).close();
            } else if (tarDataSource instanceof HikariDataSource) {
                ((HikariDataSource)tarDataSource).close();
            } else if (tarDataSource instanceof DruidDataSource) {
                ((DruidDataSource)tarDataSource).close();
            }
        }
        catch (Exception ex) {
            log.error("DynamicDataSourceBuilder build dataSource error , the eror is {} " , ex);
        }
    }
}
